/***************************************************************************
 *   Copyright (C) 2004 by cyril dupuit                                    *
 *   cyrildupuit@hotmail.com                                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

//*****************************************************************************
// Nom du module : SemInfo.c
// Description :  Obtention d'infos sur les semaphores.
//*****************************************************************************
 
// Historique :
// 28/10/04 : Creation du module V1.0  

#include "Kernel/Core.h"
#include "Misc/Console.h"
#include "Lib/Queue.h"
#include "Misc/ThredInf.h"
#include "Kernel/Schedule.h"
#include "Arch/Pentium/Kernel/Cpu.h"
#include "Lib/StdLib/stdio.h"
#include "Kernel/Thread.h"
#include "Kernel/Errors.h"

//*****************************************************************************
// But de la procedure : Afficher une liste de tous les semaphore crees
// Entree : Aucune
// Parametre retourne : TRUE si liste affichee, FALSE si liste est vide, ERROR
// si memoire insuffisante
//*****************************************************************************
Status_t SemListShow(void)
{
	QueueID_t QueueSemList;
	SemID_t SemID;
	unsigned int SemCnt;
	ThreadCount_t QueueUsed, QueueSize;
	char Tab[30];
	unsigned int Line = 0;
	Coord_t X, Y;
	unsigned int SemNbr;
	
	SemNbr = SemListCount();
	if(SemNbr == 0)
	{
		if(printf("Aucun semaphore cree.\n") == -1) return ERROR;
		return FALSE;
	}
	QueueSemList = QueueCreate(SemNbr, QUEUE_FIFO);
	if(QueueSemList == 0)
	{//Creation de la file impossible
		SetLastError(INSUFFICIENT_MEMORY_AVAILABLE);
		return ERROR;
	}
	else
	{//Creation reussie	
		if(printf("Liste des semaphores crees (%d) : \n", SemNbr) == -1) return ERROR;
		if(SemGetList(QueueSemList) == FALSE)
		{//Un semaphore a ete cree entre temps, la file d'attente est trop petite
			if(printf("La liste ci-dessous est incomplete, un semaphore vient d'etre cree !\n") == -1) return ERROR;	
		}
		if(ConsoleGetCursorPosition(&X, &Y) == ERROR) return ERROR;
		if(printf("ID : ") == -1) return ERROR;
		GotoXY(X + 15, Y);//Se placer a la ligne courante au milieu de l'ecran
		if(printf("Type : ") == -1) return ERROR;
		GotoXY(X + 30, Y);//Se placer a la ligne courante au milieu de l'ecran
		if(printf("Nb Dispo : ") == -1) return ERROR;
		GotoXY(X + 50, Y);//Se placer a la ligne courante au milieu de l'ecran
		if(printf("Taille file d'attente : \n") == ERROR) return ERROR;
		
		//Affichage des parametres des taches
		SemID = (QueueID_t)QueueRead(QueueSemList);
		while(SemID != 0)
		{//Afficher la liste des taches declarees
			if(ConsoleGetCursorPosition(&X, &Y) == ERROR) return ERROR;
			//Afficher le numero du semaphore
			GotoXY(X , Y);
			if(printf("%ld", SemID) == -1) return ERROR;
			//Afficher le type de semaphore
			GotoXY(X + 15, Y);
			if(SemTypeString(SemID, Tab, sizeof(Tab)) == ERROR) return ERROR;
			if(printf(Tab) == ERROR) return ERROR;
			//Afficher le nombre de semaphore disponible
			GotoXY(X + 30, Y);
			SemCnt = SemCount(SemID);
			if(printf("%d", SemCnt) == -1) return ERROR;
			//Afficher le nombre de place utilise dans la file d'attente
			GotoXY(X + 50, Y);
			if(SemQueueSize(SemID, &QueueUsed, &QueueSize) == ERROR) return ERROR;
			if(printf("%d/%d\n", QueueUsed, QueueSize) == -1) return ERROR;
			//Recuperer le prochain numero du semaphore
			SemID = (QueueID_t)QueueRead(QueueSemList);
			Line = (Line + 1) % 20;//20 equivaut au nombre de ligne sur la console
			if((Line == 0)&&(SemID != 0))
			{//Demander a l'utilisateur de presser une touche pour voir la suite de l'ecran
				if(Pause() != TRUE)
				{//L'utilisateur stoppe la visualisation
					while(SemID != 0)
					{//Vider la file d'attente
						QueueDelete(&QueueSemList);
						
						return TRUE;
					}
				}
			}
		}
	}
	
	QueueDelete(&QueueSemList);
	
	return TRUE;
}

//*****************************************************************************
//But de la fonction : Afficher des informations detaillees sur un semaphore
// Entree : 
//	SemID : Numero d'identification du semaphore
// Parametre retourne : ERROR si la console est invalide ou si le numero
// d'identification est invalide, TRUE sinon
//*****************************************************************************
Status_t SemShow(SemID_t SemID)
{
	ThreadID_t TaskID;
	QueueID_t QueueSemInfo;
	unsigned int Line = 0;
	ThreadCount_t ThreadCount;
	
	if(SemIDVerify(SemID) == FALSE)
	{//Le numero d'identification n'est pas le bon
		SetLastError(INCORRECT_SEMAPHORE_ID);
		return ERROR;
	}
	
	ThreadCount = SemTaskCount(SemID);
	if(ThreadCount == 0)
	{
		if(printf("Aucun thread n'est en attente sur ce semaphore\n") == -1) return ERROR;	
		return TRUE;
	}
	
	QueueSemInfo = QueueCreate(ThreadCount, QUEUE_FIFO);
	if(QueueSemInfo == 0)
	{//Creation de la file impossible
		SetLastError(INSUFFICIENT_MEMORY_AVAILABLE);
		return ERROR;
	}
	else
	{//Creation reussie	
		if(printf("File d'attente du semaphore %ld :\n", SemID) == -1) return ERROR;
		if(SemGetTaskQueue(SemID, QueueSemInfo) == FALSE)
		{//Un semaphore a ete cree entre temps, la file d'attente est trop petite
			if(printf("La liste ci-dessous est incomplete, un semaphore vient d'etre cree !\n") == -1) return ERROR;	
		}
	
		if(printf("ID Thread : \n") == -1) return ERROR;

		TaskID = (ThreadID_t)QueueRead(QueueSemInfo);
		while(TaskID != 0)
		{//Afficher la liste des taches declarees
			//Afficher le numero du descripteur de tache
			if(printf("%ld\n", TaskID) == -1) return ERROR;

			//Recuperer le prochain numero de tache
			TaskID = (ThreadID_t)QueueRead(QueueSemInfo);
			Line = (Line + 1) % 20;//20 equivaut au nombre de ligne sur la console
			if((Line == 0)&&(TaskID != 0))
			{//Demander a l'utilisateur de presser une touche pour voir la suite de l'ecran
				if(Pause() != TRUE)
				{//L'utilisateur stoppe la visualisation
					QueueDelete(&QueueSemInfo);
					
					return TRUE;
				}
			}
		}
	}
	QueueDelete(&QueueSemInfo);
	
	return TRUE;
}

//*****************************************************************************
